package org.folio.rest.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import io.vertx.core.AsyncResult;
import io.vertx.core.Context;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import org.folio.cql2pgjson.exception.FieldException;
import org.folio.rest.RestVerticle;
import org.folio.rest.impl.other.PartyUtil;
import org.folio.rest.impl.other.notify.INotify;
import org.folio.rest.impl.other.reserve_station.ReserveEndPond;
import org.folio.rest.impl.other.reserve_station.ReserveQueueService;
import org.folio.rest.impl.other.take.TenantsTaskService;
import org.folio.rest.impl.service.ReaderChangeReserve;
import org.folio.rest.impl.service.WebInfoDetailService;
import org.folio.rest.impl.util.DBName;
import org.folio.rest.jaxrs.model.*;
import org.folio.rest.jaxrs.resource.PartyWebInfo;
import org.folio.rest.persist.PgUtil;
import org.folio.rest.persist.PostgresClient;
import org.folio.rest.persist.cql.CQLWrapper;
import org.folio.rest.tools.utils.ValidationHelper;
import org.folio.util.UuidUtil;

import javax.ws.rs.core.Response;
import java.util.*;
import java.util.stream.Collectors;

import static io.vertx.core.Future.failedFuture;
import static io.vertx.core.Future.succeededFuture;

/**
 * @author lee
 * @Classname WebInfoImpl
 * @Description TODO
 * @Date 2020/7/7 10:04
 * @Created by lee
 */
public class WebInfoImpl implements PartyWebInfo {
    private final Logger logger = LoggerFactory.getLogger("modparty");

    private static final String NOTIFY_TABLE_PARTY = "party";
//order by creation_date at time zone '+8:00' desc

    @Override
    public void getPartyWebInfo(String query, int offset, int limit, String lang, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        CQLWrapper cql = null;
        if (StrUtil.isBlankOrUndefined(query)) {
            query = null;
        }
        try {
            cql = PartyUtil.getCQL(query, limit, offset, NOTIFY_TABLE_PARTY);

        } catch (Exception e) {
            ValidationHelper.handleError(e, asyncResultHandler);
            return;
        }

        PgUtil.postgresClient(vertxContext, okapiHeaders)
                .get(NOTIFY_TABLE_PARTY,org.folio.rest.jaxrs.model.PartyGroup.class, new String[]{"*"},cql,true,false,r->{
                    if (r.succeeded()) {
                        PartyCollection notes = new PartyCollection();
                        List<PartyGroup> notifyList = r.result().getResults();
                        notes.setPartyGroup(notifyList);
                        Integer totalRecords = r.result().getResultInfo().getTotalRecords();
                        notes.setTotalRecords(totalRecords);
                        asyncResultHandler.handle(succeededFuture(
                                GetPartyWebInfoResponse.respond200WithApplicationJson(notes)));
                    } else {
                        ValidationHelper.handleError(r.cause(), asyncResultHandler);
                    }
                });

    }


    @Override
    public void getPartyWebInfoDetailsAndByBarcodeAndId(String barcode, String id, String lang, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        if (StrUtil.isBlankOrUndefined(id)) {
            logger.error("The  id or barcode is null , check your request id or barcode");
            Errors valErr = ValidationHelper.createValidationErrorMessage("id", id,
                    "Your request params is empty, this is not allowed  ");
            asyncResultHandler.handle(succeededFuture(GetPartyWebInfoDetailsAndByBarcodeAndIdResponse.respond400WithTextPlain(valErr)));
            return;
        }
        PostgresClient pg = PgUtil.postgresClient(vertxContext, okapiHeaders);
        WebInfoDetailService.partyWebInfoDetail(id, barcode, pg, reply -> {
            if (reply.succeeded()) {
                PartyWebDetailsInfo result = reply.result();
                 TenantsTaskService.setIntCounter(okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT),result.getParty().getId(), replys -> {
                    if (replys.succeeded()) {
                        result.setPageViewAmount(replys.result());
                        asyncResultHandler.handle(succeededFuture(GetPartyWebInfoDetailsAndByBarcodeAndIdResponse.respond200WithApplicationJson(result)));

                    } else {
                        result.setPageViewAmount(1);
                        asyncResultHandler.handle(succeededFuture(GetPartyWebInfoDetailsAndByBarcodeAndIdResponse.respond200WithApplicationJson(result)));

                    }
                });
            } else {
                ValidationHelper.handleError(reply.cause(), asyncResultHandler);
            }
        });
    }


    @Override
    public void getPartyWebInfoParticipation(String query, int offset, int limit, String lang, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {


        CQLWrapper cqlWrapper = null;
        CQLWrapper cqlWrapper1 = null;
        CQLWrapper cqlCount1 = null;
        if (!StrUtil.isNullOrUndefined(query)) {
            try {

                if (query.contains("&&")) {
                    String queryArr[] = query.split("&&");

                    cqlCount1 =   PartyUtil.getCQL(queryArr[0], -1, -1, "r").addWrapper(PartyUtil.getCQL(queryArr[1], -1, -1, "a"));
                    //报名表查询条件
                    cqlWrapper = PartyUtil.getCQL(queryArr[0], limit, offset, "r");
                    //签到表查询条件
                    cqlWrapper1 = PartyUtil.getCQL(queryArr[1], -1, -1, "a");


                    cqlWrapper.addWrapper(cqlWrapper1);

                    //排序
                   // cqlWrapper.addWrapper(PartyUtil.getCQL( " ",-1,-1,"r"));

                } else {
                    cqlWrapper = PartyUtil.getCQL(query + " sortby metadata.createdDate/sort.descending ", limit, offset, "r");
                    cqlCount1 = PartyUtil.CQLCreate(query, -1, -1, "r");
                }


            } catch (Exception e) {
                logger.error("Incorrect request parameters");
                Errors valErr = ValidationHelper.createValidationErrorMessage("query", query,
                        "Incorrect request parameters ");
                asyncResultHandler.handle(succeededFuture(GetPartyWebInfoParticipationResponse.respond400WithTextPlain(valErr)));
                return;
            }
        }
        String tenant = okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT);
        String responseParams = "r.jsonb ->> 'id' AS reserve_id,r.jsonb ->> 'partyId' AS party_id, r.jsonb ->> 'partyName' AS party_name , r.jsonb ->> 'status' AS reserve_status ," +
                "                 r.jsonb ->> 'partyVenue' AS party_venue, r.jsonb ->> 'partyStartDate' AS party_start_date , " +
                "                 r.jsonb ->> 'reserveDate' AS reserve_date , ((jsonb_build_array(r.jsonb -> 'readerReserveGroup') -> 0) -> 0) ->> 'name' as name ," +
                "                r.jsonb ->> 'partyEndDate' AS party_end_date, r.jsonb ->> 'imageId' AS image_id , " +
                "                case when a.jsonb ->> 'attendState' is null then '5' else  a.jsonb ->> 'attendState' end attend_state , " +
                "                case when c.jsonb ->> 'score' is null then '0' else  c.jsonb ->> 'score' end score , " +
                "                case when c.jsonb ->> 'state' is null then '-1' else  c.jsonb ->> 'state' end appraisal_state ,  "+
                "                c.JSONB ->> 'appraisal' AS appraisal";

        String sql = "SELECT %s FROM " + tenant + "_mod_party.reserve r LEFT JOIN " + tenant + "_mod_party.attend a " +
                "ON r.jsonb ->> 'id' = a.jsonb ->> 'reserveId'" + " LEFT JOIN " + tenant + "_mod_party.party_appraisal c ON r.jsonb ->> 'id' = c.jsonb ->> 'reserveId'";


        HashMap<String, String> mapping = CollUtil.newHashMap();
        mapping.put("reserve_id", "reserveId");
        mapping.put("party_name", "partyName");
        mapping.put("party_id", "partyId");
        mapping.put("party_start_date", "partyStartDate");
        mapping.put("party_end_date", "partyEndDate");
        mapping.put("image_id", "imageId");
        mapping.put("absence_amount", "absenceAmount");
        mapping.put("party_venue", "partyVenue");
        mapping.put("attend_state", "attendState");
        mapping.put("name", "readerName");
        mapping.put("reserve_date", "reserveDate");
        mapping.put("reserve_status", "reserveStatus");
        mapping.put("score", "score");
        mapping.put("appraisal", "appraisal");
        mapping.put("appraisal_state","appraisalState");
        PostgresClient pg = PgUtil.postgresClient(vertxContext, okapiHeaders);
        String finalSql = sql;
        String where = cqlWrapper != null ? cqlWrapper.toString() : "";
        String searchSQL = String.format(sql, responseParams) + where;

        String countSQL = String.format(finalSql, "count(*)") + cqlCount1.toString();


        pg.select(searchSQL, reply -> {
            if (reply.succeeded()) {

                List<JsonObject> list = reply.result().getRows();
                List<WebReserveGroup> webReserveDataList = new ArrayList<>();
                list.stream().forEach(a -> {
                    WebReserveGroup readerReserveData = BeanUtil.mapToBean(a.getMap(), WebReserveGroup.class, CopyOptions.create().setFieldMapping(mapping));
                    webReserveDataList.add(readerReserveData);
                });
                WebReserveDataCollection webReserveDataCollection = new WebReserveDataCollection();
                webReserveDataCollection.setWebReserveGroup(webReserveDataList);

                pg.select(countSQL, countReply -> {
                    if (countReply.succeeded()) {
                        JsonArray records = countReply.result().getResults().get(0);
                        webReserveDataCollection.setTotalRecords(Integer.parseInt(records.getList().get(0).toString()));
                        asyncResultHandler.handle(succeededFuture(GetPartyWebInfoParticipationResponse.respond200WithApplicationJson(webReserveDataCollection)));
                    }
                });

            } else {
                ValidationHelper.handleError(reply.cause(), asyncResultHandler);
            }

        });
    }

    @Override
    public void postPartyWebInfoParticipation(String lang, WebReserveData entity, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        if (StrUtil.isNullOrUndefined(entity.getReserveId())) {

            logger.error("Incorrect request parameters");
            Errors valErr = ValidationHelper.createValidationErrorMessage("reserveId", entity.getReserveId(),
                    "Incorrect request parameters ");
            asyncResultHandler.handle(succeededFuture(PostPartyWebInfoParticipationResponse.respond400WithTextPlain(valErr)));
            return;
        }
        PostgresClient pg = PgUtil.postgresClient(vertxContext, okapiHeaders);
        pg.getById("reserve", entity.getReserveId(), ReserveGroup.class, reply -> {
            if (reply.succeeded()) {
                ReserveGroup searchResult = reply.result();
                searchResult.setIsDel(1);
                Optional<ReserveEndPond> res = TenantsTaskService.getReserveEndPond(okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT));

                if (res.isPresent()) {
                    ReserveQueueService serve =res.get().getReserveQueueService(searchResult.getPartyId());
                    if (serve !=null){
                        serve.cancelReserve(searchResult.getReaderReserveGroup().get(0).getBarcode());
                        asyncResultHandler.handle(succeededFuture(PostPartyWebInfoParticipationResponse.respond201WithApplicationJson(
                                entity, PostPartyWebInfoParticipationResponse.headersFor201()
                        )));
                        return;
                    }
                }
                pg.delete("reserve", searchResult.getId(), replyUpdate -> {
                    if (replyUpdate.succeeded()) {

                        if (replyUpdate.result().getUpdated() == 0) {
                            asyncResultHandler.handle(succeededFuture(PostPartyWebInfoParticipationResponse
                                    .respond400WithTextPlain(entity.getReserveId())));
                            return;
                        }
                        CQLWrapper cql = PartyUtil.CQLCreate(" reserveId == " + searchResult.getId(), -1, -1, "attend");
                        pg.delete("attend", cql, replyDel -> {
                            if (replyDel.result().getUpdated() == 0) {
                                asyncResultHandler.handle(succeededFuture(PostPartyWebInfoParticipationResponse
                                        .respond400WithTextPlain(entity.getReserveId())));
                                return;
                            }
                            if (replyDel.succeeded()) {
                               if (res.isPresent()) {
                                    ReserveQueueService serve =res.get().getReserveQueueService(searchResult.getPartyId());
                                    if (serve !=null){
                                        serve.cancelReserve(searchResult.getReaderReserveGroup().get(0).getBarcode());
                                        asyncResultHandler.handle(succeededFuture(PostPartyWebInfoParticipationResponse.respond201WithApplicationJson(
                                                entity, PostPartyWebInfoParticipationResponse.headersFor201()
                                        )));
                                        return;
                                    }
                                }
                                asyncResultHandler.handle(succeededFuture(PostPartyWebInfoParticipationResponse.respond201WithApplicationJson(
                                        entity, PostPartyWebInfoParticipationResponse.headersFor201()
                                )));
                            }
                        });


                    } else {
                        ValidationHelper.handleError(reply.cause(), asyncResultHandler);
                    }
                });
            } else {
                ValidationHelper.handleError(reply.cause(), asyncResultHandler);
            }
        });
    }

    @Override
    public void postPartyWebInfoParticipationChange(String lang, ReaderReserveChangeRequest entity, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        PostgresClient pg = PgUtil.postgresClient(vertxContext, okapiHeaders);
        ReaderChangeReserve.change(entity, pg, reply -> {
            if (reply.succeeded()) {
                try {
                    INotify.create(okapiHeaders, vertxContext, "1", "1").notifyCenter(reply.result(), 2);
                } catch (FieldException e) {
                    e.printStackTrace();
                }
                asyncResultHandler.handle(Future.succeededFuture(PostPartyWebInfoParticipationResponse.
                        respond201WithApplicationJson(reply.result(), PostPartyWebInfoParticipationResponse.headersFor201())));
            } else {
                Errors valErr = ValidationHelper.createValidationErrorMessage("读者证号：", entity.getBarcode(),
                        reply.cause().getMessage());
                asyncResultHandler.handle(succeededFuture(PostPartyWebInfoParticipationChangeResponse.respond400WithTextPlain(valErr)));
            }

        });
    }


    @Override
    public void postPartyWebInfoReaderReserveById(String id, String lang, Reserve entity, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {

        entity.setIsDel(0);
        entity.setReserveDate(DateUtil.formatDateTime(new Date()));
        entity.setId(UUID.randomUUID().toString());
        Party partyGroup =  TenantsTaskService.getReserveStationParty(okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT),entity.getPartyId());

        if (partyGroup == null) {
            Errors valErr = ValidationHelper.createValidationErrorMessage("name", entity.getPartyName(),
                    "这个活动尚未审核或者审核未通过，不允许报名");
            asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReaderReserveByIdResponse.respond400WithTextPlain(valErr)));
            return;
        }
        Optional<ReserveEndPond> res = TenantsTaskService.getReserveEndPond(okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT));

        if (res.isPresent()) {
            ReserveQueueService serve = res.get().getReserveQueueService(partyGroup.getId());
            WebReserveStatus status = serve.readerReserveStatus(entity.getReaderReserveGroup().get(0).getBarcode());
            if (status == null) {
                Errors valErr = ValidationHelper.createValidationErrorMessage("Barcode", entity.getPartyName(),
                        "读者的证号不完整，系统不允许报名");
                asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReaderReserveByIdResponse.respond400WithTextPlain(valErr)));
                return;
            }
            if (status.getIsReserve()) {
                Errors valErr = ValidationHelper.createValidationErrorMessage("name", entity.getPartyName(),
                        "已经报名成功,无需重复报名!");
                asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReaderReserveByIdResponse.respond400WithTextPlain(valErr)));
                return;

            }
            if (!status.getIsReserve() && status.getRemaining() != 0) {
                Errors valErr = ValidationHelper.createValidationErrorMessage("name", entity.getPartyName(),
                        "您已正在排队报名中");
                asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReaderReserveByIdResponse.respond400WithTextPlain(valErr)));
                return;

            }
            String barcode = entity.getReaderReserveGroup().get(0).getBarcode();
            CQLWrapper cqlWrapper = PartyUtil.CQLCreate("(readerInfo.barcode == \""+barcode+"\")",-1,-1, DBName.NOTIFY_TABLE_READER_CREDIT);
            PgUtil.postgresClient(vertxContext,okapiHeaders).get( DBName.NOTIFY_TABLE_READER_CREDIT,ReaderCreditRecord.class,cqlWrapper,true,false,getReply->{
                        if (getReply.succeeded()){
                            Optional<ReaderCreditRecord> readerRecord = getReply.result().getResults().stream().filter(a -> a.getReaderInfo().getBarcode().equals(barcode)).findAny();
                            if (readerRecord.isPresent()){
                                ReaderCreditRecord readerCreditRecord = readerRecord.get();
                                Optional<PunishmentRecordGroup> punishment = readerCreditRecord.getPunishmentRecordGroup().stream().filter(a -> a.getStatus().equals("1")).findAny();
                                if (punishment.isPresent()){
                                    Errors valErr = ValidationHelper.createValidationErrorMessage("status", punishment.get().getStatus(),
                                            punishment.get().getFoulDescription());
                                    asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReaderReserveByIdResponse.respond400WithTextPlain(valErr)));
                                    return;

                                }
                            }
                            serve.addReserve(entity);
                            WebReserveStatus result = serve.readerReserveStatus(entity.getReaderReserveGroup().get(0).getBarcode());
                            entity.setWebReserveStatus(result);
                            asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReaderReserveByIdResponse.respond201WithApplicationJson(entity, PostPartyWebInfoReaderReserveByIdResponse.headersFor201())));

                        }

                    }
            );
        }else {
            Errors valErr = ValidationHelper.createValidationErrorMessage("err", entity.getPartyName(),
                    "内部出错,报名失败");
            asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReaderReserveByIdResponse.respond400WithTextPlain(valErr)));
            return;
        }




    }

    @Override
    public void getPartyWebInfoCalendar(String query, String lang, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        if (StrUtil.isBlankOrUndefined(query)) {
            logger.error("Incorrect request parameters");
            Errors valErr = ValidationHelper.createValidationErrorMessage("query", query,
                    "查询条件不能为空 ");
            asyncResultHandler.handle(succeededFuture(GetPartyWebInfoCalendarResponse.respond400WithTextPlain(valErr)));
            return;
        }

        String begin = DateUtil.beginOfMonth(DateUtil.parse(query)).toString();
        String end = DateUtil.endOfMonth(DateUtil.parse(query)).toString();
        String sql = "isDel = 0 and approval = 1 and partyStartDate >= " + begin + " and partyEndDate <= " + end;
        CQLWrapper cql = PartyUtil.CQLCreate(sql, -1, -1, "party");
        PgUtil.postgresClient(vertxContext, okapiHeaders).get("party", PartyGroup.class, new String[]{"*"}, cql, false, false, reply -> {
            if (reply.succeeded()) {
                List<PartyGroup> list = reply.result().getResults();
                Map<String, CalendarGroup> map = new HashMap<>();
                for (PartyGroup p :
                        list) {


                    String key = DateUtil.parse(p.getPartyStartDate()).toString("d");
                    if (map.get(key) != null) {
                        CalendarGroup calendarGroup = map.get(key);
                        int amount = calendarGroup.getAmount() + 1;
                        calendarGroup.setAmount(amount);
                        calendarGroup.setDay(key);
                        map.put(key, calendarGroup);
                    } else {
                        CalendarGroup calendarGroup = new CalendarGroup();
                        calendarGroup.setAmount(1);
                        calendarGroup.setDay(key);
                        map.put(key, calendarGroup);
                    }
                }
                List<CalendarGroup> calendarCollectionList = map.values().stream().collect(Collectors.toList());
                CalendarCollection calendarCollection = new CalendarCollection();
                calendarCollection.setCalendarGroup(calendarCollectionList);
                asyncResultHandler.handle(succeededFuture(GetPartyWebInfoCalendarResponse.respond200WithApplicationJson(calendarCollection)));
            } else {

                asyncResultHandler.handle(Future.failedFuture("查询失败！ "));
            }
        });
    }


    @Override
    public void getPartyWebInfoProperty(String query, int offset, int limit, String lang, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        CQLWrapper cql = null;
        try {
            // 将查询条件语句转换成适合数据库查询的CQL 语句，并返回 CQL 对象
            cql = PartyUtil.getCQL(query, limit, offset, "property");

        } catch (Exception e) {
            //查询条件转换可能出现的异常处理
            ValidationHelper.handleError(e, asyncResultHandler);
            return;
        }
        //初始化数据库连接，并调用其中的 Get 方法 异步进行查询操作
        PgUtil.postgresClient(vertxContext, okapiHeaders)
                .get("property", org.folio.rest.jaxrs.model.PropertyGroup.class, new String[]{"*"}, cql,
                        true, false,
                        reply -> {
                            if (reply.succeeded()) {
                                //将查询结果存放到使用RMB框架构建生成的对象中
                                PropertyCollection notes = new PropertyCollection();
                                List<PropertyGroup> propertyGroupList
                                        = reply.result().getResults();
                                notes.setPropertyGroup(propertyGroupList);
                                Integer totalRecords = reply.result().getResultInfo().getTotalRecords();
                                notes.setTotalRecords(totalRecords);
                                //异步通知调用方，同样使用标准化构建的对象方法进行通知
                                asyncResultHandler.handle(Future.succeededFuture(
                                        GetPartyWebInfoPropertyResponse.respond200WithApplicationJson(notes)));
                            } else {
                                ValidationHelper.handleError(reply.cause(), asyncResultHandler);
                            }
                        });
    }

    @Override
    public void getPartyWebInfoAppraisal(String query, int offset, int limit, String lang, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        AppraisalCollection entity = new AppraisalCollection();
        entity.setAppraisalGroup(new ArrayList<>());
        entity.setTotalRecords(0);
        if (StrUtil.isBlankOrUndefined(query)) {
            logger.debug("getPartyWebInfoAppraisal: query  is Blank Or Undefined ");
            asyncResultHandler.handle(succeededFuture(GetPartyWebInfoAppraisalResponse.respond200WithApplicationJson(entity)));
            return;
        }
        PostgresClient pgUtil = PgUtil.postgresClient(vertxContext, okapiHeaders);
        CQLWrapper cql = null;
        try {
            cql = PartyUtil.getCQL(query, limit, offset, "party_appraisal");
        } catch (Exception e) {
            logger.debug(e);
            asyncResultHandler.handle(succeededFuture(GetPartyWebInfoAppraisalResponse.respond200WithApplicationJson(entity)));
            return;
        }
        pgUtil.get("party_appraisal", AppraisalGroup.class, cql, true, false, reply -> {
            if (reply.succeeded()) {
                entity.setTotalRecords(reply.result().getResultInfo().getTotalRecords());
                entity.setAppraisalGroup(reply.result().getResults());
            } else {
                logger.debug(reply.cause().getMessage());
            }
            asyncResultHandler.handle(succeededFuture(GetPartyWebInfoAppraisalResponse.respond200WithApplicationJson(entity)));
        });
    }

    @Override
    public void postPartyWebInfoAppraisal(String lang, Appraisal entity, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        PostgresClient pgUtil = PgUtil.postgresClient(vertxContext, okapiHeaders);

        String query = " partyId == *\"" + entity.getPartyId() + "\"*" + " and  reserveId == *\"" + entity.getReserveId() + "\"*";
        entity.setId(UUID.randomUUID().toString());
        entity.setCreateDate(DateUtil.formatDateTime(new Date()));
        CQLWrapper cql = null;
        try {

            cql = PartyUtil.getCQL(query, -1, -1, "party_appraisal");

        } catch (Exception e) {

            ValidationHelper.handleError(e, asyncResultHandler);
            return;
        }
        entity.setState("0");
        pgUtil.get("party_appraisal", Appraisal.class, new String[]{"*"}, cql,
                true, false, reply -> {
                    if (reply.succeeded()) {
                        Appraisal response = null;
                        if (reply.result().getResults().size() > 0) {
                            response = reply.result().getResults().get(0);
                            entity.setId(response.getId());
                            pgUtil.update("party_appraisal", entity, response.getId(), updateReply -> {
                                if (updateReply.succeeded()) {
                                    asyncResultHandler.handle(succeededFuture(PostPartyWebInfoAppraisalResponse.respond201WithApplicationJson(entity,
                                            PostPartyWebInfoAppraisalResponse.headersFor201()
                                    )));
                                } else {
                                    asyncResultHandler.handle(succeededFuture(PostPartyWebInfoAppraisalResponse.respond401WithTextPlain(entity)));
                                }
                            });
                        } else {
                            pgUtil.save("party_appraisal", entity, saveReply -> {
                                if (saveReply.succeeded()) {
                                    asyncResultHandler.handle(succeededFuture(PostPartyWebInfoAppraisalResponse.respond201WithApplicationJson(entity,
                                            PostPartyWebInfoAppraisalResponse.headersFor201()
                                    )));
                                } else {
                                    asyncResultHandler.handle(succeededFuture(PostPartyWebInfoAppraisalResponse.respond401WithTextPlain(entity)));
                                }
                            });
                        }
                    } else {
                        ValidationHelper.handleError(reply.cause(), asyncResultHandler);
                    }
                });
    }

    @Override
    public void getPartyWebInfoAppraisalDetailById(String id, String lang, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
          if (StrUtil.isBlankOrUndefined(id) || !UuidUtil.isUuid(id)){
              Appraisal valErr = new Appraisal();
              asyncResultHandler.handle(succeededFuture(GetPartyWebInfoAppraisalDetailByIdResponse.respond401WithTextPlain(valErr)));
              return;
          }
          PgUtil.getById(DBName.NOTIFY_TABLE_PARTY_APPRAISAL,Appraisal.class,id,okapiHeaders,vertxContext,
                  GetPartyWebInfoAppraisalDetailByIdResponse.class,asyncResultHandler
        );
    }

    @Override
    public void getPartyWebInfoReserveQueue(String query, int offset, int limit, String lang, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        if (StrUtil.isEmptyOrUndefined(query)) {
            logger.debug("getPartyWebInfoAppraisal: query  is Blank Or Undefined ");
            Errors valErr = ValidationHelper.createValidationErrorMessage("query", query,
                    "查询条件不能为空 ");
            asyncResultHandler.handle(succeededFuture(GetPartyWebInfoReserveQueueResponse.respond400WithTextPlain(valErr)));
            return;
        }
        List<ReserveGroup> result = new ArrayList<>();
        Optional<ReserveEndPond> res = TenantsTaskService.getReserveEndPond(okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT));

        if (res.isPresent()) {
            List<ReserveQueueService> list =  res.get().getReserveQueueServiceList();
            list.forEach(a -> {
                Optional<Reserve> reserve = a.getReaderQueue(query);
                if (reserve.isPresent()) {
                    ReserveGroup reserveGroup = new ReserveGroup();
                    BeanUtil.copyProperties(reserve.get(),reserveGroup);
                    result.add(reserveGroup);
                }
            });

        }
        ReserveCollection entity = new ReserveCollection();
        entity.setReserveGroup(result);
        entity.setTotalRecords(result.size());
        asyncResultHandler.handle(succeededFuture(GetPartyWebInfoReserveQueueResponse.respond200WithApplicationJson(entity)));


    }

    @Override
    public void postPartyWebInfoReserveQueue(String lang, Reserve entity, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
      try{
          Optional<ReserveEndPond> res = TenantsTaskService.getReserveEndPond(okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT));

          if (res.isPresent()) {
              ReserveQueueService reserveQueue =  res.get().getReserveQueueService(entity.getPartyId());
              ReaderReserveGroup readerReserve = entity.getReaderReserveGroup().get(0);
              if (reserveQueue !=null && readerReserve !=null ){
                  reserveQueue.cancelReserve(readerReserve.getBarcode());
                  asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReserveQueueResponse.respond201WithApplicationJson(entity,PostPartyWebInfoReserveQueueResponse.headersFor201())));
              }else{
                  asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReserveQueueResponse.respond400WithTextPlain(entity )));
              }

          }else{
              asyncResultHandler.handle(succeededFuture(PostPartyWebInfoReserveQueueResponse.respond400WithTextPlain(entity )));
          }
      }catch (Exception e){
          logger.info("用户取消报名排队失败:"+e.getMessage());
          asyncResultHandler.handle(failedFuture("取消报名排队失败!"));
      }
    }
}
